/*
0 * 描          述:  <描述>
 * 修  改   人:  Administrator
 * 修改时间:  2019年3月6日
 * <修改描述:>
 */
package com.tx.component.configuration.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.tx.component.configuration.dao.ConfigPropertyItemDao;
import com.tx.component.configuration.model.ConfigPropertyItem;
import com.tx.component.configuration.service.ConfigPropertyItemService;
import com.tx.core.exceptions.util.AssertUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 配置属性项业务层<br/>
 * <功能详细描述>
 *
 * @author Administrator
 * @version [版本号, 2019年3月6日]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
public class ConfigPropertyItemServiceImpl
        implements ConfigPropertyItemService {

    /** 配置属相项持久层实现 */
    private final ConfigPropertyItemDao configPropertyItemDao;

    /** <默认构造函数> */
    public ConfigPropertyItemServiceImpl(
            ConfigPropertyItemDao configPropertyItemDao) {
        super();
        this.configPropertyItemDao = configPropertyItemDao;
    }

    /**
     * @param configPropertyItem
     */
    @Override
    @Transactional
    public void insert(ConfigPropertyItem configPropertyItem) {
        AssertUtils.notNull(configPropertyItem, "configPropertyItem is null.");
        AssertUtils.notEmpty(configPropertyItem.getCode(),
                "configPropertyItem.code is empty.");
        AssertUtils.notEmpty(configPropertyItem.getName(),
                "configPropertyItem.name is empty.");
        AssertUtils.notEmpty(configPropertyItem.getModule(),
                "configPropertyItem.module is empty.");

        if (configPropertyItem.getText() == null) {
            configPropertyItem.setText("");
        }
        Date now = new Date();
        configPropertyItem.setLastUpdateDate(now);
        configPropertyItem.setCreateDate(now);

        this.configPropertyItemDao.insert(configPropertyItem);
    }

    /**
     * @param id
     * @return
     */
    @Override
    @Transactional
    public boolean deleteById(String id) {
        AssertUtils.notEmpty(id, "id is empty.");

        ConfigPropertyItem item = new ConfigPropertyItem();
        item.setId(id);

        int count = this.configPropertyItemDao.delete(item);
        boolean flag = count > 0;
        return flag;
    }

    /**
     * @param module
     * @param code
     * @return
     */
    @Override
    @Transactional
    public boolean deleteByCode(String module, String code) {
        AssertUtils.notEmpty(module, "module is empty.");
        AssertUtils.notEmpty(code, "code is empty.");

        ConfigPropertyItem item = new ConfigPropertyItem();
        item.setModule(module);
        item.setCode(code);

        int count = this.configPropertyItemDao.delete(item);
        boolean flag = count > 0;
        return flag;
    }

    /**
     * @param module
     * @param code
     * @param value
     * @return
     */
    @Override
    @Transactional
    public boolean patch(String module, String code, String value) {
        AssertUtils.notEmpty(module, "module is empty.");
        AssertUtils.notEmpty(code, "code is empty.");
        AssertUtils.notEmpty(value, "value is empty.");

        Map<String, Object> rowMap = new HashMap<>();
        rowMap.put("module", module);
        rowMap.put("code", code);
        rowMap.put("value", value);
        Date now = new Date();
        rowMap.put("lastUpdateDate", now);

        int rownum = configPropertyItemDao.update(rowMap);
        boolean res = rownum > 0;
        return res;
    }

    /**
     * @param item
     * @return
     */
    @Override
    @Transactional
    public boolean updateById(ConfigPropertyItem item) {
        AssertUtils.notNull(item, "item is null.");
        AssertUtils.notEmpty(item.getId(), "item.id is empty.");
        AssertUtils.notEmpty(item.getName(), "item.name is empty.");
        if (item.getText() == null) {
            item.setText("");
        }

        Date now = new Date();
        item.setLastUpdateDate(now);

        final Map<String, Object> rowMap = new HashMap<>();
        rowMap.put("id", item.getId());

        //rowMap.put("code", configPropertyItem.getCode());
        //rowMap.put("module", configPropertyItem.getModule());
        rowMap.put("parentId", item.getParentId());
        rowMap.put("name", item.getName());
        rowMap.put("value", item.getText());
        rowMap.put("remark", item.getRemark());
        rowMap.put("validateExpression", item.getValidateExpression());
        rowMap.put("modifiable", item.isModifiable());
        rowMap.put("leaf", item.isLeaf());
        rowMap.put("lastUpdateDate", item.getLastUpdateDate());

        int rownum = configPropertyItemDao.update(rowMap);
        boolean res = rownum > 0;

        return res;
    }

    /**
     * @param id
     * @return
     */
    @Override
    public ConfigPropertyItem findById(String id) {
        AssertUtils.notEmpty(id, "id is empty.");

        ConfigPropertyItem condition = new ConfigPropertyItem();
        condition.setId(id);
        ConfigPropertyItem item = configPropertyItemDao.find(condition);

        return item;
    }

    /**
     * @param module
     * @param code
     * @return
     */
    @Override
    public ConfigPropertyItem findByCode(String module, final String code) {
        AssertUtils.notEmpty(module, "module is empty.");
        AssertUtils.notEmpty(code, "code is empty.");

        ConfigPropertyItem condition = new ConfigPropertyItem();
        condition.setCode(code);
        condition.setModule(module);
        ConfigPropertyItem item = configPropertyItemDao.find(condition);

        return item;
    }

    /**
     * @param module
     * @param wrapper
     * @return
     */
    @Override
    public List<ConfigPropertyItem> queryList(String module, Wrapper<ConfigPropertyItem> wrapper) {
        AssertUtils.notEmpty(module, "module is empty.");

        List<ConfigPropertyItem> resList = null;
        Map<String, Object> params = new HashMap<>();
        params.put("module", module);

        resList = configPropertyItemDao.queryList(wrapper, params);
        return resList;
    }

    /**
     * @param module
     * @param parentId
     * @param wrapper
     * @return
     */
    @Override
    public List<ConfigPropertyItem> queryChildrenByParentId(String module,
                                                            String parentId, Wrapper<ConfigPropertyItem> wrapper) {
        AssertUtils.notEmpty(module, "module is empty.");
        AssertUtils.notEmpty(parentId, "parentId is empty.");

        List<ConfigPropertyItem> resList = null;
        Map<String, Object> params = new HashMap<>();
        params.put("module", module);
        params.put("parentId", parentId);

        resList = configPropertyItemDao.queryList(wrapper, params);
        return resList;
    }

    /**
     * @param module
     * @param parentId
     * @param wrapper
     * @return
     */
    @Override
    public List<ConfigPropertyItem> queryDescendantsByParentId(String module,
                                                               String parentId, Wrapper<ConfigPropertyItem> wrapper) {
        AssertUtils.notEmpty(module, "module is empty.");
        AssertUtils.notEmpty(parentId, "parentId is empty.");

        Map<String, Object> params = new HashMap<>();
        params.put("module", module);

        Set<String> ids = new HashSet<>();
        Set<String> parentIds = new HashSet<>();
        parentIds.add(parentId);

        List<ConfigPropertyItem> resListTemp = doNestedQueryList(ids,
                parentIds,
                wrapper,params);

        return resListTemp;
    }

    /**
     * 嵌套查询
     * @param ids
     * @param parentIds
     * @param wrapper
     * @param params
     * @return
     */
    private List<ConfigPropertyItem> doNestedQueryList(Set<String> ids,
                                                       Set<String> parentIds, Wrapper wrapper,
                                                       Map<String, Object> params) {
        if (CollectionUtils.isEmpty(parentIds)) {
            return new ArrayList<ConfigPropertyItem>();
        }

        //ids避免数据出错时导致无限循环
        params.put("parentIds", parentIds);
        List<ConfigPropertyItem> resList = configPropertyItemDao
                .queryList(wrapper, params);

        Set<String> newParentIds = new HashSet<>();
        for (ConfigPropertyItem cpTemp : resList) {
            if (!ids.contains(cpTemp.getId())) {
                newParentIds.add(cpTemp.getId());
            }
            ids.add(cpTemp.getId());
        }
        //嵌套查询下一层级
        resList.addAll(doNestedQueryList(ids, newParentIds, wrapper, params));

        return resList;
    }

    /**
     * @param module
     * @param params
     * @return
     */
    public List<ConfigPropertyItem> queryList(String module,
                                              Map<String, Object> params) {
        AssertUtils.notEmpty(module, "module is empty.");

        List<ConfigPropertyItem> resList = null;
        final Map<String, Object> queryParams = params == null ? new HashMap<>()
                : params;
        queryParams.put("module", module);

        resList = configPropertyItemDao.queryList(queryParams);
        return resList;
    }

    /**
     * @param module
     * @param parentId
     * @param params
     * @return
     */
    public List<ConfigPropertyItem> queryChildrenByParentId(String module,
                                                            String parentId, Map<String, Object> params) {
        AssertUtils.notEmpty(module, "module is empty.");
        AssertUtils.notEmpty(parentId, "parentId is empty.");

        params = params == null ? new HashMap<>() : params;
        params.put("module", module);
        params.put("parentId", parentId);
        List<ConfigPropertyItem> resList = configPropertyItemDao
                .queryList(params);

        return resList;
    }

    /**
     * @param module
     * @param parentId
     * @param params
     * @return
     */
    public List<ConfigPropertyItem> queryDescendantsByParentId(String module,
                                                               String parentId, Map<String, Object> params) {
        AssertUtils.notEmpty(module, "module is empty.");
        AssertUtils.notEmpty(parentId, "parentId is empty.");

        params = params == null ? new HashMap<>() : params;
        params.put("module", module);

        Set<String> ids = new HashSet<>();
        Set<String> parentIds = new HashSet<>();
        parentIds.add(parentId);

        List<ConfigPropertyItem> resListTemp = doNestedQueryList(ids,
                parentIds,
                params);

        return resListTemp;
    }

    /**
     * 查询嵌套列表<br/>
     * <功能详细描述>
     *
     * @param ids
     * @param parentIds
     * @param params
     * @return [参数说明]
     * @return List<ConfigPropertyItem> [返回类型说明]
     * @throws throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     */
    private List<ConfigPropertyItem> doNestedQueryList(Set<String> ids,
                                                       Set<String> parentIds, Map<String, Object> params) {
        if (CollectionUtils.isEmpty(parentIds)) {
            return new ArrayList<ConfigPropertyItem>();
        }

        //ids避免数据出错时导致无限循环
        Map<String, Object> queryParams = new HashMap<>();
        queryParams.putAll(params);
        queryParams.put("parentIds", parentIds);
        List<ConfigPropertyItem> resList = configPropertyItemDao
                .queryList(queryParams);

        Set<String> newParentIds = new HashSet<>();
        for (ConfigPropertyItem cpTemp : resList) {
            if (!ids.contains(cpTemp.getId())) {
                newParentIds.add(cpTemp.getId());
            }
            ids.add(cpTemp.getId());
        }
        //嵌套查询下一层级
        resList.addAll(doNestedQueryList(ids, newParentIds, params));

        return resList;
    }

}
